package pso;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import pso.particle.Particle;
import pso.position.PositionUpdateStrategy;
import pso.velocity.VelocityUpdateStrategy;
import evolution.algorithm.Iterative;
import evolution.problem.OptimizationProblem;
import evolution.stop.StopCondition;

/**
 * This class has single bounded property "iteration".
 * 
 * @author krzysiek
 * 
 */
public class PSOAlgorithmImpl implements PSOAlgorithm {

	protected int iteration;
	protected Particle[] swarm;
	protected VelocityUpdateStrategy velocityUpdateStrategy;
	protected PositionUpdateStrategy positionUpdateStrategy;
	protected StopCondition<Iterative> stopCondition;
	protected PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(
			this);
	private OptimizationProblem optimizationProblem;

	@Override
	public void runIteration() {
		positionUpdateStrategy.updatePositions(swarm);
		velocityUpdateStrategy.updateVelocities(swarm);
		incrementIteration();
	}

	@Override
	public int getCurrentIteration() {
		return iteration;
	}

	public void incrementIteration() {
		propertyChangeSupport.firePropertyChange("iteration", iteration,
				++iteration);
	}

	public void addPropertyChangeListener(String property,
			PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(property, listener);
	}

	public void removePropertyChangeListener(String property,
			PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(property, listener);
	}

	public Particle[] getSwarm() {
		return swarm;
	}

	public void setSwarm(Particle[] swarm) {
		this.swarm = swarm;
	}

	public VelocityUpdateStrategy getVelocityUpdateStrategy() {
		return velocityUpdateStrategy;
	}

	public void setVelocityUpdateStrategy(
			VelocityUpdateStrategy velocityUpdateStrategy) {
		this.velocityUpdateStrategy = velocityUpdateStrategy;
	}

	public PositionUpdateStrategy getPositionUpdateStrategy() {
		return positionUpdateStrategy;
	}

	public void setPositionUpdateStrategy(
			PositionUpdateStrategy positionUpdateStrategy) {
		this.positionUpdateStrategy = positionUpdateStrategy;
	}

	@Override
	public void run() {
		while (!stopCondition.shouldStop(this)) {
			runIteration();
		}
	}

	public StopCondition<Iterative> getStopCondition() {
		return stopCondition;
	}

	public void setStopCondition(StopCondition<Iterative> stopCondition) {
		this.stopCondition = stopCondition;
	}

	@Override
	public OptimizationProblem getOptimizationProblem() {
		return optimizationProblem;
	}

	public void setOptimizationProblem(OptimizationProblem optimizationProblem) {
		this.optimizationProblem = optimizationProblem;
	}
}
